using Domain;
using ErrorCode;
using Infrastructure;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using RabbitTraceability.Api.Applications.Command;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace RabbitTraceability.Api.Applications.CommandHandler
{
    /// <summary>
    /// 修改保健信息的命令处理器
    /// </summary>
    public class UpdateHealthCareInfoCommandHandler : IRequestHandler<UpdateHealthCareInfoCommand, bool>
    {
        private readonly IRepository<HealthCareInfo> _healthCareRepository;
        private readonly IRepository<TraceabilityInfo> _traceabilityRepository;
        private readonly ILogger<UpdateHealthCareInfoCommandHandler> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="healthCareRepository">保健信息仓储</param>
        /// <param name="traceabilityRepository">溯源信息仓储</param>
        /// <param name="logger">日志记录器</param>
        public UpdateHealthCareInfoCommandHandler(
            IRepository<HealthCareInfo> healthCareRepository,
            IRepository<TraceabilityInfo> traceabilityRepository,
            ILogger<UpdateHealthCareInfoCommandHandler> logger)
        {
            _healthCareRepository = healthCareRepository;
            _traceabilityRepository = traceabilityRepository;
            _logger = logger;
        }

        /// <summary>
        /// 处理修改保健信息的命令
        /// </summary>
        /// <param name="request">请求命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>是否修改成功</returns>
        public async Task<bool> Handle(UpdateHealthCareInfoCommand request, CancellationToken cancellationToken)
        {
            _logger.LogInformation("开始修改保健信息，保健编号：{HealthCareId}", request.HealthCareId);

            try
            {
                // 参数验证
                if (string.IsNullOrWhiteSpace(request.HealthCareId))
                {
                    _logger.LogWarning("保健编号不能为空");
                    throw new ApiException(ResultCode.参数错误, "保健编号不能为空");
                }

                // 查询现有的保健信息
                var existingHealthCare = await _healthCareRepository.GetAll()
                    .FirstOrDefaultAsync(h => h.HealthCareId == request.HealthCareId && !h.IsDeleted, cancellationToken);

                if (existingHealthCare == null)
                {
                    _logger.LogWarning("未找到保健信息，保健编号：{HealthCareId}", request.HealthCareId);
                    throw new ApiException(ResultCode.数据不存在, $"未找到保健编号为 {request.HealthCareId} 的保健信息");
                }

                // 如果批次发生变化，需要验证新批次的有效性
                if (existingHealthCare.ProductionBatch != request.ProductionBatch)
                {
                    // 验证新的生产批次是否存在
                    var traceabilityExists = await _traceabilityRepository.GetAll()
                        .AnyAsync(t => t.ProductionBatch == request.ProductionBatch && !t.IsDeleted, cancellationToken);

                    if (!traceabilityExists)
                    {
                        _logger.LogWarning("关联的生产批次不存在：{ProductionBatch}", request.ProductionBatch);
                        throw new ApiException(ResultCode.NotFound, $"关联的生产批次 '{request.ProductionBatch}' 不存在");
                    }

                    // 验证新批次是否已经有其他保健信息
                    var duplicateHealthCare = await _healthCareRepository.GetAll()
                        .AnyAsync(h => h.ProductionBatch == request.ProductionBatch && 
                                      h.HealthCareId != request.HealthCareId && 
                                      !h.IsDeleted, cancellationToken);

                    if (duplicateHealthCare)
                    {
                        _logger.LogWarning("批次已存在其他保健信息：{ProductionBatch}", request.ProductionBatch);
                        throw new ApiException(ResultCode.DuplicateRecord, $"批次 '{request.ProductionBatch}' 已存在其他保健信息");
                    }
                }

                // 更新保健信息字段
                existingHealthCare.FeedingDays = request.FeedingDays;
                existingHealthCare.HealthCareMethod = request.HealthCareMethod;
                existingHealthCare.HealthCareApproach = request.HealthCareApproach;
                existingHealthCare.ProductionBatch = request.ProductionBatch;

                // 保存更改
                await _healthCareRepository.UpdateAsync(existingHealthCare);

                _logger.LogInformation("成功修改保健信息，保健编号：{HealthCareId}，新批次：{ProductionBatch}", 
                    request.HealthCareId, request.ProductionBatch);

                return true;
            }
            catch (ApiException)
            {
                // 重新抛出API异常
                throw;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "修改保健信息时发生异常，保健编号：{HealthCareId}", request.HealthCareId);
                throw new ApiException(ResultCode.InternalServerError, "修改保健信息失败");
            }
        }
    }
} 